import json
import os
from tqdm import tqdm
from data_utils import traverse_dir
import pandas as pd
from pasers.ofd_paser.invoice import Invoice
from pasers.ofd_paser.ofd_utils import unzip_file, get_ofd_pase_dict, ofd2img
from pasers.ofd_paser.process_ofd_exception import MyOFD
from pasers.xlsx_parser.xlsx_parse import prepare_excel_table
from pasers.paser_utils import re_filter


def multi_parse(ofd_dir, unzip_path, image_saved_dir):
    """
    批量解析 OFD 文件，并在同级目录创建解压后的文件夹和保存解析结果。

    参数:
        ofd_dir (str): OFD 文件所在的目录路径。
        unzip_path (str): 解压后的文件保存路径。
        image_saved_dir (str): 解析图像保存路径。

    返回:
        tuple: 包含解析结果的列表和异常路径的列表。
    """

    # 初始化用于存储异常文件路径和解析结果的列表
    exception_ofd_path = []
    file_list = []

    # 遍历指定目录下的所有 OFD 文件
    iter_files = traverse_dir(ofd_dir, ['ofd'])
    if not iter_files:
        return [], []
    for oid, (f_path, f_name) in enumerate(tqdm(iter_files, desc='正在提取ofd文件内容')):
        # 构建 OFD 文件的解压路径
        try:
            zip_path = os.path.join(f_path)
            uf_path = unzip_file(zip_path=zip_path, unzip_path=os.path.join(unzip_path, f_name))
            # 解析 OFD 文件内容
            invoice_data = Invoice(uf_path).result_list
            # 将 OFD 文件转换为图像并保存
            img_path = ''  # ofd2img(oid, f_path, image_saved_dir)
            # 获取 OFD 文件的解析结果字典
            result_list = get_ofd_pase_dict(invoice_data, f_path, f_name, img_path)
            file_list.append(result_list)
        except Exception as e:
            # 将解析失败的文件路径添加到异常列表
            exception_ofd_path.append(uf_path)

    return file_list, exception_ofd_path


def to_row_string(row):
    """
    :param row: Series类型,其中每个元素是一个单元格信息，每个index是对应的表头信息
    :return: 转换为字符串，如 ：
    发票号码：23312000000002136011
    开票日期：2023年01月29日
    ...
    合计税额：53235.0
    """
    row_text = []
    for idx, cell in row.items():
        row_text.append(f'{idx}：{cell}')
    res = '\n'.join(row_text)
    return res


def process_df(df, block_max_len):
    """
    1. 合并df中相同文件名下的表格内容
    2. 处理后的df转换为字典
    :param df: 可解析为发票的ofd的dataframe
    :param  block_max_len:
    :return: 结果字典
    """
    table = df.loc[:, '项目名称':'税额']
    desc_before_table = df.loc[:, '购买方名称':'合计税额']
    desc_after_table = df.loc[:, '备注':]
    df_final = pd.DataFrame()

    # 去重准备工作
    files_duplicates = df['file_uuid'].tolist()
    lens = [0]
    unique_files = [files_duplicates[0]]

    for split_idx in range(1, len(files_duplicates)):
        if files_duplicates[split_idx] != files_duplicates[split_idx - 1]:
            lens.append(split_idx)
            unique_files.append(files_duplicates[split_idx])
    lens.append(len(files_duplicates))
    df_final['file_uuid'] = unique_files
    content_ls = []
    table_info_ls = []
    file_list = []
    for idx, split_idx in enumerate(range(len(lens) - 1)):
        # 基于相同的文件名分割表格
        cur_table = table.iloc[lens[split_idx]:lens[split_idx + 1], :]
        # 调用excel表格处理函数进行处理
        table_ls, extra_data_ls, _ = prepare_excel_table(cur_table, block_max_len)
        table_info = {}
        table_labels = []
        for table_id, sub_table in enumerate(table_ls):
            table_split = sub_table.split('\n')
            table_head, row_data = table_split[0:2], table_split[2:]
            table_info[f'table_{idx}_{table_id}'] = {'row_data': row_data, 'table_head': table_head}
            table_labels.append(f'<table:table_{idx}_{table_id}>')
        table_info_ls.append(table_info)
        text_before = to_row_string(desc_before_table.iloc[lens[split_idx], :])
        text_after = to_row_string(desc_after_table.iloc[lens[split_idx], :])
        if extra_data_ls:
            extra_data = '\n'.join([content[-1] for content in extra_data_ls])
            text_after = text_after + '\n' + extra_data
        content_ls.append(text_before + text_after + ''.join(table_labels))
        file_list.append(
            {"file_uuid": unique_files[idx], 'image_info': {}, 'table_info': table_info_ls[idx],
             'content': re_filter(content_ls[idx])})
    return file_list


def parse_ofd(failed_ls, ofd_dir, out_dir, unzip_dir, image_saved_dir):
    file_list, exception_ofd_path = multi_parse(ofd_dir, unzip_dir, image_saved_dir)
    if exception_ofd_path:
        # from pasers.ofd_paser.process_ofd_exception import process_exception
        for path in exception_ofd_path:
            try:
                content = MyOFD(path).get_content()
                file_uuid = os.path.basename(path)
                # content = re_filter(process_exception(path))
                file_list.append(
                    {'file_uuid': file_uuid, 'image_path': '', "is_invoice": False, 'table_info': {},
                     'content': content,
                     'file_path': path}
                )
            except Exception as e:
                failed_ls.append({'filePath': path, 'reason': str(e)})
    if file_list:
        res = {'file_num': len(file_list), 'file_suffix': 'ofd', 'file_list': file_list}
        with open(out_dir + '/ofd_content.json', 'w+', encoding='utf-8') as f:
            json.dump(res, f, ensure_ascii=False)
